using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Web.UI;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using PS.WebParts.Rollup.CalendarWebPart;
using PS.WebParts.Rollup.GridViewWebPart;

namespace PS.WebParts
{
    public class CalendarWebPart 
        : DataWebPartBase
    {

        #region public webpart properties

        [
            DefaultValue(1),
            Category("Behaivor"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Calendar Type"),
            Browsable(false)
        ]
        public int CalendarType
        {
            get { return calendarType; }
            set { calendarType = value; }
        }

        [
            DefaultValue("Month"),
            Category("Behaivor"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Default view"),
            Browsable(true)
        ]
        public string DefaultView
        {
            get { return defaultView; }
            set { defaultView = value; }
        }

        [
            DefaultValue("ltr"),
            Category("Behaivor"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Direction"),
            Browsable(true)
        ]
        public string CalendarDirection
        {
            get { return direction; }
            set { direction = value; }
        }

        [
            DefaultValue(8),
            Category("Behaivor"),
            WebPartStorage(Storage.Shared),
            FriendlyName("WorkDayStartHour"),
            Description("Work day start hour :0-23"),
            Browsable(true)
        ]
        public short WorkDayStartHour
        { 
            get { return workDayStartHour; }
            set { workDayStartHour = value; }
        }

        [
            DefaultValue(16),
            Category("Behaivor"),
            WebPartStorage(Storage.Shared),
            FriendlyName("WorkDayEndHour"),
            Description("Work day end hour :0-23"),
            Browsable(true)
        ]
        public short WorkDayEndHour
        {
            get { return workDayEndHour; }
            set { workDayEndHour = value; }
        }

        [
            DefaultValue("0111110"),
            Category("Behaivor"),
            WebPartStorage(Storage.Shared),
            FriendlyName("WorkWeek"),
            Description("Work week : '0111110'"),
            Browsable(true)
        ]
        public string WorkWeek
        {
            get { return workWeek; }
            set { workWeek = value; }
        }
        
        [
            DefaultValue("EventDate"),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Raise Event Date"),
            Browsable(true)
        ]
        public string StartDateField
        {
            get { return startDateField; }
            set { startDateField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Finish Event Date"),
            Browsable(true)
        ]
        public string EndDateField
        {
            get { return endDateField; }
            set { endDateField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Event name"),
            Browsable(true)
        ]
        public string TitleField
        {
            get { return titleField; }
            set { titleField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("All day event"),
            Browsable(true)
        ]
        public string AllDayEventField
        {
            get { return allDayEventField; }
            set { allDayEventField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Item ID"),
            Browsable(true)
        ]
        public string ItemIdField
        {
            get { return itemIdField; }
            set { itemIdField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Description"),
            Browsable(false)
        ]
        public string DescField
        {
            get { return descField; }
            set { descField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Location"),
            Browsable(false)
        ]
        public string LocationField
        {
            get { return locationField; }
            set { locationField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Recurrence"),
            Browsable(true)
        ]
        public string RecurrenceField
        {
            get { return recurrenceField; }
            set { recurrenceField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Recurrence Exc"),
            Browsable(false)
        ]
        public string RecurrenceExcField
        {
            get { return recurrenceExcField; }
            set { recurrenceExcField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Workspace Link"),
            Browsable(false)
        ]
        public string WorkspaceLinkField
        {
            get { return workspaceLinkField; }
            set { workspaceLinkField = value; }
        }

        [
            DefaultValue(""),
            Category("Data"),
            WebPartStorage(Storage.Shared),
            FriendlyName("Display Form Url"),
            Browsable(true)
        ]
        public string DispFormUrlField
        {
            get { return dispFormUrlField; }
            set { dispFormUrlField = value; }
        }

        #endregion

        private int calendarType = 1;
        private string defaultView = CalendarViewType.Month.ToString();
        private string direction = "ltr";
        private short workDayStartHour = 8;
        private short workDayEndHour = 16;
        private string workWeek = "0111110";

        private string startDateField = "Modified";
        private string endDateField = "Modified";
        private string titleField = "Title";
        private string allDayEventField;
        private string itemIdField = "_ItemID";
        private string descField;
        private string locationField;
        private string recurrenceField;
        private string recurrenceExcField;
        private string workspaceLinkField;
        private string dispFormUrlField = "_ItemUrl";

        private DateTime date;
        private CalendarDataSource source;
        private SPCalendarBase calendarControl;
        private CalendarControl chrome;

        public IDataSource DataSource
        {
            get
            {
                return DataSources[0];
            }
        }        
        
        public override ToolPart[] GetToolParts()
        {
            List<ToolPart> toolParts = new List<ToolPart>(base.GetToolParts());

            toolParts.Insert(0, new DataSourceToolPart<CalendarWebPart>(this, "Calendar Properties"));

            return toolParts.ToArray();
        }

        public abstract class CalendarWrapper 
            : SPCalendarBase
        {
            public static void SetDate(SPCalendarBase o, string value)
            {
                o.SelectedDate = value;
            }
        }

        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            try
            {                
                string viewName = Page.Request["CalendarPeriod"];
                if (String.IsNullOrEmpty(viewName))
                {
                    viewName = defaultView;
                }
                
                string calendarDate = Page.Request["CalendarDate"];
                if (!String.IsNullOrEmpty(calendarDate))
                {
                    date = DateTime.Parse(calendarDate);
                }
                else
                {
                    date = DateTime.Today;
                }

                chrome = (CalendarControl)Page.LoadControl("~/_controltemplates/CustomCalendar.ascx");

                Controls.Add(chrome);

                if (CalendarViewType.Day.ToString().ToLower() == viewName.ToLower())
                {
                    calendarControl = new DailyCalendarView();

                    chrome.ViewName = CalendarViewType.Day;
                    chrome.PreviousDate = date.AddDays(-1).ToString("d");
                    chrome.NextDate = date.AddDays(+1).ToString("d");
                    chrome.SelectedDate = date.ToString("D");
                }
                else if (CalendarViewType.Week.ToString().ToLower() == viewName.ToLower())
                {
                    calendarControl = new WeeklyCalendarView();

                    chrome.ViewName = CalendarViewType.Week;
                    chrome.PreviousDate = date.AddDays(-7).ToString("d");
                    chrome.NextDate = date.AddDays(+7).ToString("d");
                    chrome.SelectedDate = WeekRange(date);
                }
                else // (CalendarViewType.Month.ToString().ToLower() == viewName)
                {
                    MonthlyCalendarView monthlyCalendar = new MonthlyCalendarView();

                    string expandedWeeks = ExpandedWeeks;

                    if (!String.IsNullOrEmpty(expandedWeeks))
                    {
                        monthlyCalendar.ExpandedWeeks = expandedWeeks;
                    }

                    calendarControl = monthlyCalendar;

                    chrome.ViewName = CalendarViewType.Month;
                    chrome.PreviousDate = date.AddMonths(-1).ToString("d");
                    chrome.NextDate = date.AddMonths(+1).ToString("d");
                    chrome.SelectedDate = date.ToString("y");
                }
                
                CalendarWrapper.SetDate(calendarControl, date.ToString("d"));

                calendarControl.DownLevelRendering = false;
                Controls.Add(calendarControl);
            }
            catch (Exception e)
            {
                RegisterError(e.Message);
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            chrome.Direction = direction;
           
            source = new CalendarDataSource(DataSource);
            source.StartDateField = startDateField;
            source.EndDateField = endDateField;
            source.TitleField = titleField;
            source.CalendarType = calendarType;
            source.StartDateField = startDateField;
            source.EndDateField = endDateField;
            source.TitleField = titleField;
            source.AllDayEventField = allDayEventField;
            source.ItemIdField = itemIdField;
            source.DescField = descField;
            source.LocationField = locationField;
            source.RecurrenceField = recurrenceField;
            source.RecurrenceExcField = recurrenceExcField;
            source.WorkspaceLinkField = workspaceLinkField;
            source.DispFormUrlField = dispFormUrlField;
            source.Direction = direction;

            calendarControl.Calendar = (SPCalendarType)calendarType;
            calendarControl.ShowAllData = true;
            calendarControl.WorkWeek = workWeek;
            calendarControl.WorkDayStartHour = workDayStartHour;
            calendarControl.WorkDayEndHour = workDayEndHour;

            calendarControl.DataSource = source;
            calendarControl.DataBind();

            base.OnPreRender(e);
        }

        private string ExpandedWeeks
        {
            get
            {
                string expandedWeeks = SPUtility.GetExpandedWeeks(this.Context.Request);
                if (!string.IsNullOrEmpty(expandedWeeks))
                {
                    return expandedWeeks;
                }
                return (string)Context.Items["ExpandedWeeks"];
            }
        }

        private static string WeekRange(DateTime date)
        {
            DateTime beginOfWeek = date.AddDays(- (int) date.DayOfWeek);
            DateTime endOfWeek = beginOfWeek.AddDays(7);
            return String.Format("{0} - {1} {2}", beginOfWeek.ToString("m"), endOfWeek.ToString("m"), endOfWeek.Year);
        }
    }
}
